/*
 * {CopyRightNotice}
 */
package jf.jextn.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import jf.jextn.JExtn;

/**
 * @author Sandeep Kadyan
 */
public class Properties extends java.util.Properties {
    private static final long serialVersionUID = 1L;

    private static final int MAX_NESTED_LIMIT = 10;
    private int nestedLimited;

    public Properties(java.util.Properties defaults) {
        this(defaults, MAX_NESTED_LIMIT);
    }

    public Properties(java.util.Properties defaults, int nestedLevel) {
        super(defaults);
        nestedLimited = JExtn.getNearestMaximum(nestedLevel, 0, MAX_NESTED_LIMIT);
    }

    public Properties() {
        this(null);
    }

    public Properties(int nestedLevel) {
        this(null, nestedLevel);
    }

    // ****************** code-compatible stuff start ******************

    @Override
    public Object put(Object key, Object value) {
        return super.put((String) key, (String) value);
    }

    @Override
    public Object get(Object key) {
        return internalGet((String) key, 0);
    }

    /*
     * Implementation Note:- This method is overridden here because of the wrong implementation in
     * java.util.Property class. The super class should not use super keyword while invoking get()
     * method.
     */
    @Override
    public String getProperty(String key) {
        String sval = (String) get(key);
        return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
    }

    // ****************** code-compatible stuff end ******************

    /**
     * This method try to substitute the value from the other key.
     */
    private synchronized String internalGet(String key, int level) {
        // need to check the resolution of the property value.
        // this is different from the java Properties implementation.
        String val = (String) super.get(key);
        if (val == null && defaults != null)
            val = defaults.getProperty(key);

        if (val != null) {
            if (val.length() > 0 && val.charAt(0) == '@') {
                if (level >= nestedLimited)
                    return null;
                String newKey = val.substring(1);
                val = internalGet(newKey, ++level);
            }
        }
        return val;
    }

    @Override
    public synchronized void load(InputStream inStream) throws IOException {
        load(new InputStreamReader(inStream, "utf-8"));
    }

    @Override
    public synchronized void load(Reader reader) throws IOException {
        super.load(reader);
    }

}
